/**
 * 获取页面高度
 * @returns {number} 页面高度
 */
export function getPageHeight() {
  var g = document,
    a = g.body,
    f = g.documentElement,
    d = g.compatMode == "BackCompat" ? a : g.documentElement;
  return Math.max(f.scrollHeight, a.scrollHeight, d.clientHeight);
}
/**
 * 获取页面宽度
 * @returns {number} 页面宽度
 */
export function getPageWidth() {
  var g = document,
    a = g.body,
    f = g.documentElement,
    d = g.compatMode == "BackCompat" ? a : g.documentElement;
  return Math.max(f.scrollWidth, a.scrollWidth, d.clientWidth);
}

/**
 * 元素是否在视窗内
 * @param {*} el
 * @returns {boolean} true 元素在视窗内 false 元素不在视窗内
 */
export function isInViewPort(el) {
  //获取屏幕高度
  let windowTop =
    window.innerHeight ||
    document.documentElement.clientHeight ||
    document.body.clientHeight;
  // 获取元素相对视窗的位置
  const { top, bottom } = el.getBoundingClientRect();
  if (bottom > 0 && top < windowTop) {
    // 已经进入可视区
    console.log("已经进入可视区");
    return true;
  } else {
    // 未进入可视区
    console.log("未进入可视区");
    return false;
  }
}

let lastPageYOffset = 0;
let lastScrollBehavior = "auto";

export function $(el) {
  return document.querySelector(el);
}

/**
 * 在垂直方向锁定页面滚动
 **/
export function lockPageYScroll() {
  const doc = document.documentElement;
  lastPageYOffset =
    window.pageYOffset || doc.scrollTop || document.body.scrollTop;
  lastScrollBehavior = doc.style.scrollBehavior;
  doc.style.cssText = `height:100%;overflow:hidden;position:relative;`;
}

/**
 * 在垂直方向释放页面滚动的锁定
 **/
export function unlockPageYScroll() {
  const doc = document.documentElement;
  doc.style.cssText = `height:auto;overflow:auto;`;
  doc.scrollTop = lastPageYOffset || 0;
}

/** 用于删除所有标签的內联样式 */
const AllInlineStyles =
  /<(a|img|p|b|div|span|font|h1|h2|h3|h4|h5|h6|strong|italic) (.*?)(style=('[^']*?'|"[^"]*?"))(.*?)>/g;

/**
 * 过滤指定标签的內联样式
 * @param {string} rawHtml 原始 html 字符串
 * @param {string[]|string} [tagsToStrip] 需要过滤的标签数组，如果不传，则过滤所有标签的內联样式
 * @returns {string} 过滤內联样式的 html 字符串
 */
export default function stripInlineStyle(rawHtml, tagsToStrip) {
  if (!rawHtml) return "";

  // 不含标签的文本无需处理
  if (rawHtml.indexOf("<") === -1) return rawHtml;

  // 删除所有标签的內联样式
  if (!tagsToStrip || tagsToStrip.length <= 0) {
    return doStrip(rawHtml, AllInlineStyles);
  }

  // 删除指定标签的內联样式
  const normalized = normalizeTags(tagsToStrip);
  const stripReg = createRegExp(normalized);
  return doStrip(rawHtml, stripReg);
}

/**
 * 规范化标签数组
 * @param {string|string[]} tags 标签数组
 * @returns {string[]}
 */
function normalizeTags(tags) {
  let result = [];
  if (typeof tags === "string") {
    result.push(tags);
  } else if (Array.isArray(tags)) {
    result = tags;
  } else {
    throw new Error("invalid argument, tags: " + tags);
  }

  return result;
}

/**
 * 执行过滤內联样式的操作
 * @param {string} rawHtml 原始字符串
 * @param {RegExp} stripReg 过滤正则表达式
 * @returns {string}
 */
function doStrip(rawHtml, stripReg) {
  let result = rawHtml.replace(stripReg, "<$1 $2$5>");
  return stripBlanksBeforeGreaterThan(result);
}

/**
 * 创建动态正则表达式
 * @param {string[]} arr
 * @returns {RegExp}
 */
function createRegExp(arr) {
  const str = `<(${arr.join("|")}) (.*?)(style=('[^']*?'|"[^"]*?"))(.*?)>`;
  return new RegExp(str, "g");
}

/**
 * 删除大于号前的空白符号
 * @param {string} rawHtml
 * @returns {string}
 */
function stripBlanksBeforeGreaterThan(rawHtml) {
  if (!rawHtml) return "";
  return rawHtml
    .replace(/<(.*?)(\s*)>/g, "<$1>") // 删除大于号前的空格
    .replace(/<(.*?)\s+\/>/g, "<$1 />"); // 将 /> 前的多个空格压缩为一个空格
}

/**
 * 清除字符串里的标签
 * @param str
 * @returns {string}
 */
function removeHtmlTag(str = "") {
  return str.replace(/<[^<>]+>/g, "").replace(/&nbsp/g, "");
}

/**
 * 向元素添加Class
 * @param el
 * @param cls
 */
export function addClass(el, cls) {
  if (!el) return;
  var curClass = el.className;
  var classes = (cls || "").split(" ");

  for (var i = 0, j = classes.length; i < j; i++) {
    var clsName = classes[i];
    if (!clsName) continue;

    if (el.classList) {
      el.classList.add(clsName);
    } else if (!hasClass(el, clsName)) {
      curClass += " " + clsName;
    }
  }
  if (!el.classList) {
    el.setAttribute("class", curClass);
  }
}

/**
 * 向元素删除Class
 * @param el
 * @param cls
 */
export function removeClass(el, cls) {
  if (!el || !cls) return;
  var classes = cls.split(" ");
  var curClass = " " + el.className + " ";

  for (var i = 0, j = classes.length; i < j; i++) {
    var clsName = classes[i];
    if (!clsName) continue;

    if (el.classList) {
      el.classList.remove(clsName);
    } else if (hasClass(el, clsName)) {
      curClass = curClass.replace(" " + clsName + " ", " ");
    }
  }
  if (!el.classList) {
    el.setAttribute("class", trim(curClass));
  }
}

/**
 *
 * @desc 判断元素是否有某个class
 * @param {HTMLElement} ele
 * @param {String} cls
 * @return {Boolean}
 */
export function hasClass(ele, cls) {
  return new RegExp("(\\s|^)" + cls + "(\\s|$)").test(ele.className);
}

// 当前到浏览器左边的位置
export function getElementViewLeft(element) {
  let actualLeft = element.offsetLeft;
  let current = element.offsetParent;
  let elementScrollLeft = 0;

  while (current !== null) {
    actualLeft += current.offsetLeft;
    current = current.offsetParent;
  }

  if (document.compatMode == "BackCompat") {
    elementScrollLeft = document.body.scrollLeft;
  } else {
    elementScrollLeft = document.documentElement.scrollLeft;
  }

  return actualLeft - elementScrollLeft;
}
// 当前到浏览器顶部的位置
export function getElementViewTop(element) {
  let actualTop = element.offsetTop;
  let current = element.offsetParent;
  let elementScrollTop = 0;

  while (current !== null) {
    actualTop += current.offsetTop;
    current = current.offsetParent;
  }

  if (document.compatMode == "BackCompat") {
    elementScrollTop = document.body.scrollTop;
  } else {
    elementScrollTop = document.documentElement.scrollTop;
  }

  return actualTop - elementScrollTop;
}
// 距离文档顶部 左侧的距离
export function getElPositionAbs(element) {
  let actualLeft = element.offsetLeft;
  let actualTop = element.offsetTop;
  let current = element.offsetParent;
  while (current !== null) {
    actualLeft += current.offsetLeft;
    actualTop += current.offsetTop;
    current = current.offsetParent;
  }

  return [actualLeft, actualTop];
}
